﻿// ----------------------------------------------------------------------------------------
// Author:                    Magaly Vargas y Joaquín López
// Company:                   ALBALIA INTERACTIVA S.L.
// Assembly version:          1.0.0.0
// Date:                      22/02/2010
// Time:                      12:00
// Solution Name:             OffInvoiceWordAddIn
// Solution Filename:         OffInvoiceWordAddIn
// Solution FullFilename:     C:\Desarrollo\OffInvoiceWordAddIn
// Project Name:              OffInvoiceWordAddIn
// Project Filename:          OffInvoiceWordAddIn.csproj
// Project FullFilename:      C:\Desarrollo\OffInvoiceWordAddIn\OffInvoiceWordAddIn.csproj
// Project Item Name:         ImportInvoiceController.cs
// Project Item Filename:     ImportInvoiceController.cs
// Project Item FullFilename: C:\Desarrollo\OffInvoiceWordAddIn\ImportInvoiceController.cs
// Project Item Kind:         Código
// Purpose:                   
//Copyright © 2009 - 2010 Albalia Interactiva S.L. Reservados todos los derechos.
// ----------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using OffInvoiceWordAddIn.UBLFiles;
using System.Windows.Forms;
using System.IO;
using OffInvoiceWordAddIn.FacturaeFiles;
using OffInvoiceWordAddIn.CIIFiles;

namespace OffInvoiceWordAddIn
{

    /// <summary>
    /// Clase que controla la importación de los datos de una factura.
    /// </summary>
    class ImportInvoiceController
    {
        #region "Fields"

        /// <summary>
        /// Campo con el documento XML que se va a importar
        /// </summary>
        private XmlDocument doc = null;

        /// <summary>
        /// Campo que indica si la factura es en papel o electrónica
        /// </summary>
        private bool papel = true;

        /// <summary>
        /// Campo con el path donde se encuentra la factura
        /// </summary>
        private string filePath = string.Empty;


        #endregion

        #region "Constructors"

        /// <summary>
        /// Contructor que inicia la importación
        /// </summary>
        /// <param name="filePath">Path de la factura</param>
        public ImportInvoiceController(string filePath)
        {
            this.filePath = filePath;
            this.doc = new XmlDocument();
            doc.PreserveWhitespace = true;
            try
            {
                doc.Load(filePath);
            }
            catch (Exception)
            {

                throw new Exception(ControlMessages.Msg.XmlMalformed.ToString("g"));
            }
            if (doc.DocumentElement.NamespaceURI.Equals("urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"))
            {
                importUBL();
            }
            else if (doc.DocumentElement.NamespaceURI.Equals("urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:1"))
            {
                importCII();
            }
            else
            {
                importFacturae();

            }
        }

        #endregion

        #region "Privated Methods"

        /// <summary>
        /// Método que se encarga de la importación de una factura en formato UBL, además de realizar la validación
        /// a 3 niveles para mostrar los resultados al usuario si lo desea
        /// </summary>
        private void importUBL()
        {
            XmlDocument docSinFirma = new XmlDocument();
            docSinFirma.PreserveWhitespace = true;
            docSinFirma.LoadXml(doc.OuterXml);

            XmlNode signatureNode = docSinFirma.DocumentElement.GetElementsByTagName("Signature").Item(0);
            if (signatureNode != null)
            {
                docSinFirma.DocumentElement.GetElementsByTagName("Signature", "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2").Item(0).RemoveChild(signatureNode);
            }
            ResultUBLValidation schemaV = UBLValidation.SchemaValidation(docSinFirma);
            ResultUBLValidation accountV = UBLValidation.AccountValidation(doc);
            ResultUBLValidation signedV = UBLValidation.SignedValidation(doc);
            LoadController load = new LoadController();
            load.LoadUBL(filePath, true, false, true);
            loadBlockDocument();
            papel = false;
            if (showMessages(schemaV.Success, accountV.Success, signedV.Success, ControlMessages.Msg.MsgInfoSchemaUBL.ToString("g")))
            {
                ValidateController v = new ValidateController();
                v.validateUBL(doc, false);
            }
        }

        /// <summary>
        /// Método que se encarga de la importación de una factura en formato Facturae, además de realizar la validación
        /// a 3 niveles para mostrar los resultados al usuario si lo desea
        /// </summary>
        private void importFacturae()
        {
            bool schema = true;
            bool account = true;
            bool signed = true;

            try
            {
                LoadController load = new LoadController();
                load.LoadFacturae(filePath, false, true, true);
            }
            catch (Exception)
            {
                schema = false;
                throw new Exception("1");
            }
            ValidateController v = new ValidateController();
            try
            {
                if (doc.DocumentElement.NamespaceURI.Equals("http://www.facturae.es/Facturae/2007/v3.1/Facturae"))
                {
                    v.AccountingValidation(filePath, true, InvoceTypes.FACTURAE_3_1);
                }
                else if (doc.DocumentElement.NamespaceURI.Equals("http://www.facturae.es/Facturae/2009/v3.2/Facturae"))
                {
                    v.AccountingValidation(filePath, true, InvoceTypes.FACTURAE_3_2);
                }

            }
            catch (Exception)
            {
                account = false;
            }

            try
            {
                v.SignatureValidations(filePath);
            }
            catch (Exception)
            {
                signed = false;
            }
            loadBlockDocument();
            if (showMessages(schema, account, signed, ControlMessages.Msg.MsgInfoSchemaFacturae31.ToString("g")))
            {
                if (papel)
                {
                    if (doc.DocumentElement.NamespaceURI.Equals("http://www.facturae.es/Facturae/2007/v3.1/Facturae"))
                    {
                        v.validatePaper(InvoceTypes.FACTURAE_3_1, false);
                    }
                    else if (doc.DocumentElement.NamespaceURI.Equals("http://www.facturae.es/Facturae/2009/v3.2/Facturae"))
                    {
                        v.validatePaper(InvoceTypes.FACTURAE_3_2, false);
                    }

                }
                else
                {
                    v.validateFacturae(doc, false);
                }
            }
        }

        /// <summary>
        /// Método que se encarga de la importación de una factura en formato CII, además de realizar la validación
        /// a 3 niveles para mostrar los resultados al usuario si lo desea
        /// </summary>
        private void importCII()
        {
            XmlDocument docSinFirma = new XmlDocument();
            docSinFirma.PreserveWhitespace = true;
            docSinFirma.LoadXml(doc.OuterXml);

            XmlNode signatureNode = docSinFirma.DocumentElement.GetElementsByTagName("Signature").Item(0);
            if (signatureNode == null)
                signatureNode = docSinFirma.DocumentElement.GetElementsByTagName("ds:Signature").Item(0);
            if (signatureNode != null)
            {
                docSinFirma.DocumentElement.RemoveChild(signatureNode);
            }
            ResultCIIValidation schemaV = CIIValidation.SchemaValidation(docSinFirma);
            ResultCIIValidation accountV = CIIValidation.AccountValidation(doc);
            ResultCIIValidation signedV = CIIValidation.SignedValidation(doc);
            LoadController load = new LoadController();
            load.LoadCII(filePath, true, false,true);
            loadBlockDocument();
            papel = false;
            if (showMessages(schemaV.Success, accountV.Success, signedV.Success, ControlMessages.Msg.MsgInfoSchemaCII.ToString("g")))
            {
                ValidateController v = new ValidateController();
                v.validateCII(doc, false);
            }
        }


        /// <summary>
        /// Método que se encarga de bloquear los campos de la factura para evitar modificaciones ilegales
        /// </summary>
        private void loadBlockDocument()
        {
            try
            {
                string tempDir = Path.GetTempPath();

                string data = doc.OuterXml;
                if (data.IndexOf("Signature") > 0)
                {
                    papel = false;
                    Globals.ThisAddIn.AddCustomXmlPart(data, Globals.ThisAddIn.Application.ActiveDocument);
                }

                string name = "";

                try
                {
                    name = string.Concat(Globals.ThisAddIn.GetControlValue(ControlList.Tag.SP_TaxIdentificationNumber), Globals.ThisAddIn.GetControlValue(ControlList.Tag.IH_InvoiceNumber), Globals.ThisAddIn.GetControlValue(ControlList.Tag.IH_InvoiceSeriesCode));
                }
                catch (Exception) { }

                object filename;

                if (string.IsNullOrEmpty(name))
                    filename = Path.GetTempFileName();
                else
                    filename = tempDir + name;

                object missing = System.Reflection.Missing.Value;
                Globals.ThisAddIn.Application.ActiveDocument.SaveAs(ref filename, ref missing, ref missing, ref missing, ref missing, ref missing,
                ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);

            }
            catch (Exception) { }

        }


        /// <summary>
        /// Método que muestra un mensaje informativo después de realizar la importación de una factura.
        /// </summary>
        /// <param name="schema">Resultado de la validación del esquema de la factura</param>
        /// <param name="account">Resultado de la validación contable de la factura</param>
        /// <param name="signed">Resultado de la validación de firma de la factura</param>
        /// <param name="msgInfoSchema">Mensaje informativo par mostrar</param>
        /// <returns>True o False si el usuario desea ver los datos de validación</returns>
        private bool showMessages(bool schema, bool account, bool signed, string msgInfoSchema)
        {
            ControlMessages msg = ControlMessages.getInstance();
            if (!schema || !account || (!signed && !papel))
            {
                string error = msg.getMessage(ControlMessages.Msg.ErrorSchema) + " " + msg.getMessage(ControlMessages.Msg.ErrorFails) + "\n";
                if (!schema)
                    error += "  " + msg.getMessage(msgInfoSchema) + "\n";
                if (!account)
                    error += "  " + msg.getMessage(ControlMessages.Msg.MsgAccounValidation) + "\n";
                if (!signed)
                    error += "  " + msg.getMessage(ControlMessages.Msg.MsgSing) + "\n";
                error += msg.getMessage(ControlMessages.Msg.MsgInfoViewDetails);
                if (MessageBox.Show(error, msg.getMessage(ControlMessages.Msg.CaptionFacturae), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    return true;
                }
            }
            else
            {
                if (MessageBox.Show(msg.getMessage(ControlMessages.Msg.InfoImportOK), msg.getMessage(ControlMessages.Msg.CaptionFacturae), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    return true;
                }
            }
            return false;
        }

        #endregion

    }
}
